//
//  LBRadialGradient.mm
//  OpenGLGame
//
//  Created by Nguyen Cong Huy on 12/1/12.
//  Copyright (c) 2012 UIT. All rights reserved.
//

#include <iostream>
#include "LBRadialGradientFilter.h"
#include "LBGraphics.h"

char radialGradientFilterFragStr[] = ""
"precision highp float;"

"varying vec2 vtexCoor;"
"varying vec4 vposition;"

"uniform float opacity;"
"uniform sampler2D texture;"
"uniform vec2 center;"
"uniform vec4 centerColor;"
"uniform vec4 outterColor;"


// soft light function (opacity equal 1/2 value in photoshop)
"vec4 softLight(vec4 base, vec4 blend, float opacity){"
"   vec4 white = vec4(1.0, 1.0, 1.0, 1.0);"
"   vec4 lumCoeff = vec4(0.2125, 0.7154, 0.0721, 1.0);"
"   vec4 result;"

"   float luminance = dot(base, lumCoeff);"
"   if (luminance < 0.45)"
"       result = 2.0 * blend * base;"
"   else if (luminance > 0.55)"
"       result = white - 2.0 * (white - blend) * (white - base);"
"   else"
"   {"
"       vec4 result1 = 2.0 * blend * base;"
"       vec4 result2 = white - 2.0 * (white - blend) * (white - base);"
"       result = mix(result1, result2, (luminance - 0.45) * 10.0);"
"   }"
"    result = mix(base, result, opacity);"
"   return result;"
"}"
// END soft light function

//brightness function (default 0.0)
"vec4 brightnessColor(vec4 color, float brightness){"
"color.r = color.r + brightness;"
"color.g = color.g + brightness;"
"color.b = color.b + brightness;"
"color = clamp(color, 0.0, 1.0);"
"return color;"
"}"
//END brightness function

"vec4 radialGradientColor(vec4 centerColor, vec4 outerColor, vec2 myPosition, vec2 centerPosition){"
"    float distance = clamp(distance(myPosition, centerPosition), 0.0, 1.0);"
"    return mix(centerColor, outerColor, distance);"
"}"

"void main()"
"{"
"   lowp vec4 textureColor = texture2D(texture, vtexCoor);"
"   vec4 blend = radialGradientColor(centerColor, outterColor, vposition.xy, center);"
"   vec4 result = softLight(textureColor, blend, opacity);"
"    gl_FragColor = result;"
"}"
;

LBRadialGradientFilter::LBRadialGradientFilter(){
    init(0, radialGradientFilterFragStr);
    
    centerUniform = program->uniformIndex("center");
    centerColorUniform = program->uniformIndex("centerColor");
    outterColorUniform = program->uniformIndex("outterColor");
    opacityUniform = program->uniformIndex("opacity");
    
    setCenter(0.0f, 0.0f);
    setCenterColor(0.5f, 0.5f, 0.5f);
    setOutterColor(0.0f, 0.0f, 0.0f);
    setOpacity(1.0f);
}

void LBRadialGradientFilter::setCenter(float x, float y){
    center.one = x;
    center.two = y;
    LBGraphics::getInstance()->useProgram(program);
    glUniform2f(centerUniform, x, y);
}

void LBRadialGradientFilter::setCenterColor(float red, float green, float blue){
    centerColor.one = red;
    centerColor.two = green;
    centerColor.three = blue;
    LBGraphics::getInstance()->useProgram(program);
    glUniform4f(centerColorUniform, red, green, blue, 1.0f);
}

void LBRadialGradientFilter::setOutterColor(float red, float green, float blue){
    outterColor.one = red;
    outterColor.two = green;
    outterColor.three = blue;
    LBGraphics::getInstance()->useProgram(program);
    glUniform4f(outterColorUniform, red, green, blue, 1.0f);
}

void LBRadialGradientFilter::setOpacity(float opacity){
    this->opacity = opacity;
    LBGraphics::getInstance()->useProgram(program);
    glUniform1f(opacityUniform, opacity);
}